/*
 * Created on 2006-6-5
 *
 */
package whf.framework.report.export.view;

import java.util.Map;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFPrintSetup;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;

import whf.framework.datasource.DataRow;
import whf.framework.report.export.Export;
import whf.framework.report.export.ReportBuilder;
import whf.framework.util.StringUtils;
import whf.framework.util.Utils;
import whf.framework.web.tag.TableModel;
import whf.framework.web.tag.ext.IColumn;

/**
 * @author wanghaifeng
 *
 */
public class XlsView extends AbstractView {
	public static final int WIDTH_MULT = 450; // width per char

	public static final int MIN_CHARS = 8; // minimum char width

	public static final short DEFAULT_FONT_HEIGHT = 8;

	public static final short LARGE_FONT_HEIGHT = 16;

	public static final double NON_NUMERIC = -.99999;

	public static final String DEFAULT_MONEY_FORMAT = "$###,###,##0.00";

	public static final String DEFAULT_PERCENT_FORMAT = "##0.0%";

	public static final String NBSP = "&nbsp;";

	private HSSFWorkbook wb;

	private HSSFSheet sheet;

	private HSSFPrintSetup ps;

	private Map styles;

	private short rownum;

	private short cellnum;

	private HSSFRow hssfRow;

	private String moneyFormat;

	private String percentFormat;
	
	public XlsView(ReportBuilder model, TableModel tableModel) {
		super(model, tableModel);
	}

	public void beforeBody() {

		if (StringUtils.isEmpty(moneyFormat)) {
			moneyFormat = DEFAULT_MONEY_FORMAT;
		}

		if (StringUtils.isEmpty(percentFormat)) {
			percentFormat = DEFAULT_PERCENT_FORMAT;
		}
		wb = new HSSFWorkbook();
		sheet = wb.createSheet();
		wb.setSheetName(0, "第一页", HSSFWorkbook.ENCODING_UTF_16);
		
		styles = initStyles(wb);
		ps = sheet.getPrintSetup();

		sheet.setAutobreaks(true);
		ps.setFitHeight((short) 1);
		ps.setFitWidth((short) 1);

		createHeader();
	}

	public void doBody() {
		dataSource.iterator();
		while(dataSource.hasNext()) {
			DataRow row = dataSource.next();
			for (int col = 0; col < this.columns.size(); col++) {
				IColumn tc = this.columns.get(col);
				if (col == 0) {
					rownum++;
					cellnum = 0;
					hssfRow = sheet.createRow(rownum);
				}
				HSSFCell hssfCell = hssfRow.createCell(cellnum);
				hssfCell.setEncoding(HSSFWorkbook.ENCODING_UTF_16);
				hssfCell.setCellType(HSSFCell.CELL_TYPE_STRING);
				String propertyValue = null;
				try{
					propertyValue = row.getPropertyDisplay(tc.getProperty());
				} catch(Exception e){
					propertyValue = e.toString();
				}
				writeToCellFormatted(hssfCell, propertyValue);
				cellnum++;
			}
		}
	}

	public Object afterBody() {
		return wb;
	}

	private void createHeader() {
		rownum = 0;
		cellnum = 0;
		Export export = model.getExportHandler().getCurrentExport();
		String HeaderTitle = export.getHeaderTitle();
		HSSFRow row0 = sheet.createRow(rownum);
		int index = (this.columns.size() / 2);
		HSSFCell cellHead = row0.createCell((short) index);
		cellHead.setCellType(HSSFCell.CELL_TYPE_STRING);
		cellHead.setEncoding(HSSFWorkbook.ENCODING_UTF_16);
		cellHead.setCellStyle((HSSFCellStyle) styles.get("headTitleStyle"));
		cellHead.setCellValue(HeaderTitle);

		HSSFRow row = sheet.createRow(++rownum);
		for (int i = 0; i < this.columns.size(); i++) {
			IColumn tc = this.columns.get(i);
			HSSFCell cell = row.createCell(cellnum);
			cell.setEncoding(HSSFCell.ENCODING_UTF_16);
			cell.setCellStyle((HSSFCellStyle) styles.get("titleStyle"));
			cell.setCellType(HSSFCell.CELL_TYPE_STRING);
			cell.setCellValue(tc.getDisplayTitle());
			int valWidth = (tc.getDisplayTitle() + "").length() * WIDTH_MULT;
			sheet.setColumnWidth(cell.getCellNum(), (short) valWidth);
			cellnum++;
		}
	}

	private void writeToCellFormatted(HSSFCell cell, String value) {
		double numeric = NON_NUMERIC;
		if (value.trim().equals(NBSP)) {
			value = "";
		}
		cell.setCellStyle((HSSFCellStyle) styles.get("textStyle"));

		fixWidthAndPopulate(cell, numeric, value);
	}

	private void fixWidthAndPopulate(HSSFCell cell, double numeric, String value) {
		int valWidth = 0;

		if (numeric != NON_NUMERIC) {
			cell.setCellValue(numeric);
			valWidth = (cell.getNumericCellValue() + "$,.").length()
					* WIDTH_MULT;
		} else {
			cell.setCellValue(value);
			valWidth = (cell.getStringCellValue() + "").length() * WIDTH_MULT;

			if (valWidth < (WIDTH_MULT * MIN_CHARS)) {
				valWidth = WIDTH_MULT * MIN_CHARS;
			}
		}

		if (valWidth > sheet.getColumnWidth(cell.getCellNum())) {
			sheet.setColumnWidth(cell.getCellNum(), (short) valWidth);
		}
	}

	private Map initStyles(HSSFWorkbook wb) {
		return initStyles(wb, DEFAULT_FONT_HEIGHT);
	}

	private Map<String, HSSFCellStyle> initStyles(HSSFWorkbook wb, short fontHeight) {
		Map<String, HSSFCellStyle> result = Utils.newHashMap();
		HSSFCellStyle titleStyle = wb.createCellStyle();
		HSSFCellStyle headTitleStyle = wb.createCellStyle();
		HSSFCellStyle textStyle = wb.createCellStyle();
		HSSFCellStyle boldStyle = wb.createCellStyle();
		result.put("headTitleStyle", headTitleStyle);
		result.put("titleStyle", titleStyle);
		result.put("textStyle", textStyle);
		result.put("boldStyle", boldStyle);

		// Global fonts
		HSSFFont font = wb.createFont();
		font.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
		font.setColor(HSSFColor.BLACK.index);
		font.setFontName(HSSFFont.FONT_ARIAL);
		font.setFontHeightInPoints(fontHeight);

		HSSFFont fontBold = wb.createFont();
		fontBold.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
		fontBold.setColor(HSSFColor.BLACK.index);
		fontBold.setFontName(HSSFFont.FONT_ARIAL);
		fontBold.setFontHeightInPoints(fontHeight);

		HSSFFont largeFontBold = wb.createFont();
		largeFontBold.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
		largeFontBold.setColor(HSSFColor.BLACK.index);
		largeFontBold.setFontName(HSSFFont.FONT_ARIAL);
		largeFontBold.setFontHeightInPoints(LARGE_FONT_HEIGHT);
		/*
		 * // Money Style moneyStyle.setFont(font);
		 * moneyStyle.setAlignment(HSSFCellStyle.ALIGN_RIGHT);
		 * moneyStyle.setDataFormat(format.getFormat(moneyFormat));
		 *  // Money Style Bold moneyStyleBold.setFont(fontBold);
		 * moneyStyleBold.setAlignment(HSSFCellStyle.ALIGN_RIGHT);
		 * moneyStyleBold.setDataFormat(format.getFormat(moneyFormat));
		 *  // Percent Style percentStyle.setFont(font);
		 * percentStyle.setAlignment(HSSFCellStyle.ALIGN_RIGHT);
		 * percentStyle.setDataFormat(format.getFormat(percentFormat));
		 *  // Percent Style Bold // percentStyleBold.setFont(fontBold); //
		 * percentStyleBold.setAlignment(HSSFCellStyle.ALIGN_RIGHT); //
		 * percentStyleBold.setDataFormat(format.getFormat(percentFormat));
		 *  // Standard Numeric Style // numericStyle.setFont(font); //
		 * numericStyle.setAlignment(HSSFCellStyle.ALIGN_RIGHT);
		 *  // Standard Numeric Style Bold //
		 * numericStyleBold.setFont(fontBold); //
		 * numericStyleBold.setAlignment(HSSFCellStyle.ALIGN_RIGHT);
		 */

		// Title Style
		headTitleStyle.setFont(largeFontBold);
		headTitleStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		headTitleStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
		// Title Style
		titleStyle.setFont(fontBold);
		//titleStyle.setFillForegroundColor(HSSFColor.GREY_25_PERCENT.index);
		//titleStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
		titleStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
		titleStyle.setBottomBorderColor(HSSFColor.BLACK.index);
		titleStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
		titleStyle.setLeftBorderColor(HSSFColor.BLACK.index);
		titleStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
		titleStyle.setRightBorderColor(HSSFColor.BLACK.index);
		titleStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
		titleStyle.setTopBorderColor(HSSFColor.BLACK.index);
		titleStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		titleStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
		titleStyle.setWrapText(true);
		// Standard Text Style
		textStyle.setFont(font);
		textStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
		textStyle.setBottomBorderColor(HSSFColor.BLACK.index);
		textStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
		textStyle.setLeftBorderColor(HSSFColor.BLACK.index);
		textStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
		textStyle.setRightBorderColor(HSSFColor.BLACK.index);
		textStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
		textStyle.setTopBorderColor(HSSFColor.BLACK.index);
		textStyle.setWrapText(true);

		// Standard Text Style
		boldStyle.setFont(fontBold);
		boldStyle.setWrapText(true);

		return result;
	}
}